#include <e32def.h>
#include <eikenv.h>

#include <COMMDB.H>
#include <CommDbConnPref.h>
#include <aknpopup.h> 
#include <aknlists.h> 
#include <es_enum.h>  // TConnectionInfoBuf
#include <http.h>

#include "HttpConnectionEngine.h"

CHttpConnectionEngine* CHttpConnectionEngine::iConnectionEngine = NULL;

CHttpConnectionEngine::CHttpConnectionEngine()
{
    iSession = new RHTTPSession();
    iSession->OpenL();
    this->iRfs = CEikonEnv::Static()->FsSession();
    iIapID = 0;
    iCookieContainer = new TaobaoCookieContainer;
    iConnectionSetupDone = EFalse;
    iUrl = NULL;
    iQueryData=new(ELeave)COrderQueryData;
    
}
CHttpConnectionEngine::~CHttpConnectionEngine()
{
    if (iSession)
    {
        iSession->Close();
        delete iSession;
    }
    if (iSocketServ.Handle() != 0)
    {
        iConnection.Close();
        iSocketServ.Close();
    }
    if (iCookieContainer)
    {
        int count, i;
        TaobaoCookie *aCookie;
        count = iCookieContainer->Count();
        for (i = 0; i < count; i++)
        {
            aCookie = (*iCookieContainer)[i];
            TaobaoCookieDestroy(aCookie);
        }
        iCookieContainer->Reset();
        delete iCookieContainer;
    }
    if (iUrl)
    {
        delete iUrl;
    }
    if(iQueryData)
    {
        delete iQueryData;
    }
}
CHttpConnectionEngine* CHttpConnectionEngine::GetInstance()
{
    if (!iConnectionEngine)
    {
        iConnectionEngine = new CHttpConnectionEngine();
    }
    return iConnectionEngine;
}

void CHttpConnectionEngine::Destroy()
{
    if (iConnectionEngine)
    {
        delete iConnectionEngine;
        iConnectionEngine = NULL;
    }
}

CHttpConnection* CHttpConnectionEngine::HttpRequest( const TDesC8 &aUri,
        const TDesC8 &aReferer, TInt aMethod, const TDesC8 &aData,
        TActionType actionType, const TDesC &aFileName,
        MHttpRevObserver *aObserver)
{
    CHttpConnection *connection = new CHttpConnection(iRfs, aFileName);
    ConnectGPRSL();
    connection->HttpRequest(iSession, aUri, aReferer, aMethod, aData,
            actionType, aObserver);
    return connection;
}

void CHttpConnectionEngine::Cancel( CHttpConnection *connection)
{
    if (connection)
    {
        connection->Cancel();
    }
}

void CHttpConnectionEngine::ConnectGPRSL()
{
    if (iConnectionSetupDone)// && FindExistingConnection())
    {
        return;
    }

    // IAP Selected
    // Open socket server and start the connection
    User::LeaveIfError(iSocketServ.Connect());
    User::LeaveIfError(iConnection.Open(iSocketServ));
    if (!iConnectionSetupDone)
    {
        // Now we have the iap Id. Use it to connect for the connection
        TCommDbConnPref connectPref;
        // Setup preferences 
        connectPref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
        connectPref.SetDirection(ECommDbConnectionDirectionOutgoing);
        // Sets the CommDb ID of the IAP to use for this connection
        connectPref.SetIapId(iIapID);
        // Start connection
        User::LeaveIfError(iConnection.Start(connectPref));
    }
    // Set the sessions connection info...
    RStringPool strPool = iSession->StringPool();
    RHTTPConnectionInfo connInfo = iSession->ConnectionInfo();
    // ...to use our socket server and connection
    connInfo.SetPropertyL(strPool.StringF(HTTP::EHttpSocketServ,
            RHTTPSession::GetTable()), THTTPHdrVal(iSocketServ.Handle()));
    // ...to use our connection
    connInfo.SetPropertyL(strPool.StringF(HTTP::EHttpSocketConnection,
            RHTTPSession::GetTable()), THTTPHdrVal(REINTERPRET_CAST(TInt, &(iConnection))));

    iConnectionSetupDone = ETrue;
}

void CHttpConnectionEngine::setIapID( TUint32 aIapID)
{
    iIapID = aIapID;
}

TUint32 CHttpConnectionEngine::IapID()
{
    if (iConnection.SubSessionHandle())
    {
        _LIT(KCommdbIapSetting, "IAP\\Id");
        //User::LeaveIfError(iConnection.GetIntSetting(KCommdbIapSetting,iIapID));
        TRAPD(err, iConnection.GetIntSetting(KCommdbIapSetting,iIapID));
    }
    return iIapID;
}

RSocketServ CHttpConnectionEngine::getRSocketServ()
{
    return iSocketServ;
}

RConnection CHttpConnectionEngine::getRConnection()
{
    return iConnection;
}

TBool CHttpConnectionEngine::FindExistingConnection()
{
    TBool connected = EFalse;
    TConnectionInfoBuf connInfo;
    TUint count;
    if (iConnection.EnumerateConnections(count) == KErrNone)
    {
        for (TUint i = 1; i <= count; i++)
        {
            // Note: GetConnectionInfo expects 1-based index.
            if (iConnection.GetConnectionInfo(i, connInfo) == KErrNone)
            {
                if (connInfo().iIapId == iIapID)
                {
                    connected = ETrue;
                    break;
                }
            }
        }
    }
    return connected;
}

TaobaoCookieContainer *CHttpConnectionEngine::GetCookieContainer()
{
    return iCookieContainer;
}

void CHttpConnectionEngine::TaobaoCookieDestroy( TaobaoCookie *aCookie)
{
    if (aCookie)
    {
        if (aCookie->key)
        {
            delete aCookie->key;
        }
        if (aCookie->value)
        {
            delete aCookie->value;
        }
        if (aCookie->domain)
        {
            delete aCookie->domain;
        }
        if (aCookie->prefix)
        {
            delete aCookie->prefix;
        }
        if (aCookie->expires)
        {
            delete aCookie->expires;
        }
        free(aCookie);
    }
}

TaobaoCookie* CHttpConnectionEngine::TaobaoCookieAlloc()
{
    TaobaoCookie *aCookie;
    int size;
    size = sizeof(TaobaoCookie);
    aCookie = (TaobaoCookie*) malloc(size);
    memset(aCookie, 0, size);
    return aCookie;
}

RFs CHttpConnectionEngine::GetRfs()
{
    return this->iRfs;
}

void CHttpConnectionEngine::SetUrl( const TDesC8 &aUrl)
{
    if (iUrl)
    {
        delete iUrl;
        iUrl = NULL;
    }
    iUrl = aUrl.Alloc();
}

HBufC8 *CHttpConnectionEngine::GetUrl()
{
    return iUrl;
}

COrderQueryData *CHttpConnectionEngine::GetOrderQueryData()
{
    return iQueryData;
}
